package com.itheima.server;

import org.json.JSONObject;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

// WebSocket端点处理类
@ServerEndpoint("/")
public class ChatEndpoint {
    // 存储所有连接的会话


    private static final Set<Session> sessions = Collections.newSetFromMap(new ConcurrentHashMap<>());
    // 简单的回复消息库
    private static final List<String> replyTemplates = Arrays.asList(
            "收到您的消息: %s",
            "感谢您的反馈，关于 '%s' 我会记录下来",
            "您提到了 '%s'，这是一个很有趣的话题",
            "我理解您的意思是: %s",
            "关于 '%s'，我可以提供更多信息"
    );
    // 日期格式化器
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // 存储用户名与会话的映射
    private static final Map<Session, String> userSessions = new ConcurrentHashMap<>();
    // 存储房间信息 (房间ID -> 会话列表)
    private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap<>();

    // 添加显式的默认构造函数
    public ChatEndpoint() {
        // 默认构造函数
    }

    // 登录时关联用户名与会话
    public void login(Session session, String username) {
        userSessions.put(session, username);
        // 默认加入大厅
        try {
            joinRoom(session, "general");
        } catch (Exception e) {
            System.err.println("加入默认房间失败: " + e.getMessage());
        }
    }

    // 加入房间
    public void joinRoom(Session session, String roomId) {
        // 先离开当前房间
        leaveCurrentRoom(session);

        // 加入新房间
        rooms.computeIfAbsent(roomId, k -> Collections.newSetFromMap(new ConcurrentHashMap<>()))
                .add(session);

        // 广播房间内用户列表
        try {
            broadcastUserList(roomId);
        } catch (Exception e) {
            System.err.println("广播房间用户列表失败: " + e.getMessage());
        }
    }

    // 离开当前房间
    private void leaveCurrentRoom(Session session) {
        for (Map.Entry<String, Set<Session>> entry : rooms.entrySet()) {
            String roomId = entry.getKey();
            Set<Session> roomSessions = entry.getValue();

            if (roomSessions.remove(session)) {
                // 如果房间为空，可以选择删除房间或保留
                if (roomSessions.isEmpty()) {
                    // 可选：rooms.remove(roomId);
                }

                // 广播房间用户列表更新
                try {
                    broadcastUserList(roomId);
                } catch (Exception e) {
                    System.err.println("广播房间用户列表失败: " + e.getMessage());
                }
                break;
            }
        }
    }

    // 获取会话所在的房间
    private String getCurrentRoom(Session session) {
        for (Map.Entry<String, Set<Session>> entry : rooms.entrySet()) {
            if (entry.getValue().contains(session)) {
                return entry.getKey();
            }
        }
        return null;
    }

    // 获取用户名
    private String getUsername(Session session) {
        return userSessions.getOrDefault(session, "匿名用户");
    }

    // 登出
    private void logout(Session session) {
        leaveCurrentRoom(session);
        userSessions.remove(session);
    }

    // 广播房间用户列表
    private void broadcastUserList(String roomId) throws IOException {
        Set<Session> roomSessions = rooms.getOrDefault(roomId, Collections.emptySet());
        List<String> usernames = new ArrayList<>();

        for (Session session : roomSessions) {
            if (session.isOpen()) {
                usernames.add(getUsername(session));
            }
        }

        JSONObject userListMessage = new JSONObject();
        userListMessage.put("type", "userList");
        userListMessage.put("users", usernames);

        broadcastToRoom(roomId, userListMessage.toString());
    }

    // 广播消息到房间
    private void broadcastMessageToRoom(String roomId, Session sender, String username, String content, String timestamp) throws IOException {
        JSONObject chatMessage = new JSONObject();
        chatMessage.put("type", "chat");
        chatMessage.put("username", username);
        chatMessage.put("content", content);
        chatMessage.put("timestamp", timestamp);

        // 发送给房间内所有用户（包括发送者自己）
        Set<Session> roomSessions = rooms.getOrDefault(roomId, Collections.emptySet());
        for (Session session : roomSessions) {
            if (session.isOpen()) {
                sendMessage(session, chatMessage.toString());
            }
        }
    }

    // 连接建立时调用
    @OnOpen
    public void onOpen(Session session) {
        sessions.add(session);
        System.out.println("新客户端连接，会话ID: " + session.getId());

        // 发送欢迎消息
        try {
            JSONObject welcomeMsg = new JSONObject();
            welcomeMsg.put("type", "system");
            welcomeMsg.put("content", "欢迎使用TECH CHAT 3000系统，我是您的机械助手");
            sendMessage(session, welcomeMsg.toString());
        } catch (Exception e) {
            System.err.println("发送欢迎消息失败: " + e.getMessage());
        }
    }

    // 收到消息时调用
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("收到来自 " + session.getId() + " 的消息: " + message);

        try {
            // 解析客户端消息
            // 这里我们需要解析前端发送的JSON格式消息
            org.json.JSONObject jsonMessage = new org.json.JSONObject(message);
            String type = jsonMessage.getString("type");

            switch (type) {
                case "login":
                    String username = jsonMessage.getString("username");
                    login(session, username);
                    // 发送登录成功消息
                    org.json.JSONObject loginResponse = new org.json.JSONObject();
                    loginResponse.put("type", "system");
                    loginResponse.put("content", "登录成功，欢迎 " + username + "！");
                    sendMessage(session, loginResponse.toString());
                    break;

                case "joinRoom":
                    String roomId = jsonMessage.getString("room");
                    joinRoom(session, roomId);
                    // 发送房间切换确认消息
                    org.json.JSONObject roomChangeResponse = new org.json.JSONObject();
                    roomChangeResponse.put("type", "roomChange");
                    roomChangeResponse.put("room", roomId);
                    sendMessage(session, roomChangeResponse.toString());

                    // 广播房间内用户列表更新
                    broadcastUserList(roomId);
                    break;

                case "chat":
                    String content = jsonMessage.getString("content");
                    String timestamp = jsonMessage.getString("timestamp");
                    String currentRoom = getCurrentRoom(session);
                    username = jsonMessage.getString("username"); // 从消息中获取用户名

                    if (currentRoom != null) {
                        // 广播消息到房间
                        broadcastMessageToRoom(currentRoom, session, username, content, timestamp);
                    }
                    break;

                case "logout":
                    logout(session);
                    break;

                default:
                    // 处理普通消息（向后兼容）
                    Message clientMsg = Message.fromJson(message);
                    String replyContent = generateReply(clientMsg.getContent());
                    Message replyMsg = new Message(replyContent, new Date());
                    sendMessage(session, replyMsg.toJson());
                    break;
            }
        } catch (Exception e) {
            System.err.println("处理消息时出错: " + e.getMessage());
            e.printStackTrace();
            try {
                org.json.JSONObject errorMsg = new org.json.JSONObject();
                errorMsg.put("type", "system");
                errorMsg.put("content", "抱歉，消息处理失败");
                sendMessage(session, errorMsg.toString());
            } catch (Exception ex) {
                System.err.println("发送错误消息失败: " + ex.getMessage());
            }
        }
    }

    // 连接关闭时调用
    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        sessions.remove(session);
        userSessions.remove(session);
        leaveCurrentRoom(session);
        System.out.println("客户端断开连接，会话ID: " + session.getId() +
                "，原因: " + closeReason.getReasonPhrase());
    }

    // 发生错误时调用
    @OnError
    public void onError(Session session, Throwable error) {
        System.err.println("会话 " + session.getId() + " 发生错误: " + error.getMessage());
    }

    // 发送消息给指定会话
    private void sendMessage(Session session, String message) throws IOException {
        synchronized (session) {
            if (session.isOpen()) {
                session.getBasicRemote().sendText(message);
            }
        }
    }

    // 生成回复消息
    private String generateReply(String userMessage) {
        Random random = new Random();
        int index = random.nextInt(replyTemplates.size());
        return String.format(replyTemplates.get(index), userMessage);
    }

    // 向房间内所有成员广播消息
    private void broadcastToRoom(String roomId, String message) throws IOException {
        Set<Session> roomSessions = rooms.getOrDefault(roomId, Collections.emptySet());
        for (Session s : roomSessions) {
            if (s.isOpen()) {
                sendMessage(s, message);
            }
        }
    }

    // 获取房间在线人数
    private int getRoomUserCount(String roomId) {
        Set<Session> roomSessions = rooms.getOrDefault(roomId, Collections.emptySet());
        return roomSessions.size();
    }
}
